/*
 *    Copyright (c) 2017-2023 AsyncHttpClient Project. All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.asynchttpclient.cookie;

import io.netty.handler.codec.http.cookie.Cookie;
import org.asynchttpclient.uri.Uri;
import org.asynchttpclient.util.Counted;

import java.net.CookieManager;
import java.util.List;
import java.util.function.Predicate;

/**
 * This interface represents an abstract store for {@link Cookie} objects.
 *
 * <p>{@link CookieManager} will call {@code CookieStore.add} to save cookies
 * for every incoming HTTP response, and call {@code CookieStore.get} to
 * retrieve cookie for every outgoing HTTP request. A CookieStore
 * is responsible for removing HttpCookie instances which have expired.
 *
 * @since 2.1
 */
public interface CookieStore extends Counted {

    /**
     * Adds one {@link Cookie} to the store. This is called for every incoming HTTP response.
     * If the given cookie has already expired it will not be added.
     *
     * <p>A cookie to store may or may not be associated with a URI. If it
     * is not associated with a URI, the cookie's domain and path attribute
     * will indicate where it comes from. If it is associated with a URI and
     * its domain and path attribute are not specified, given URI will indicate
     * where this cookie comes from.
     *
     * <p>If a cookie corresponding to the given URI already exists,
     * then it is replaced with the new one.
     *
     * @param uri    the {@link Uri uri} this cookie associated with. if {@code null}, this cookie will not be associated with a URI
     * @param cookie the {@link Cookie cookie} to be added
     */
    void add(Uri uri, Cookie cookie);

    /**
     * Retrieve cookies associated with given URI, or whose domain matches the given URI. Only cookies that
     * have not expired are returned. This is called for every outgoing HTTP request.
     *
     * @param uri the {@link Uri uri} associated with the cookies to be returned
     * @return an immutable list of Cookie, return empty list if no cookies match the given URI
     */
    List<Cookie> get(Uri uri);

    /**
     * Get all not-expired cookies in cookie store.
     *
     * @return an immutable list of http cookies;
     * return empty list if there's no http cookie in store
     */
    List<Cookie> getAll();

    /**
     * Remove a cookie from store.
     *
     * @param predicate that indicates what cookies to remove
     * @return {@code true} if this store contained the specified cookie
     * @throws NullPointerException if {@code cookie} is {@code null}
     */
    boolean remove(Predicate<Cookie> predicate);

    /**
     * Remove all cookies in this cookie store.
     *
     * @return true if any cookies were purged.
     */
    boolean clear();

    /**
     * Evicts all the cookies that expired as of the time this method is run.
     */
    void evictExpired();
}
